package com.wwinsoft.modules.orm.mybatis;

import java.util.List;
import java.util.Map;

import org.apache.commons.beanutils.PropertyUtils;
import org.apache.ibatis.session.RowBounds;
import org.mybatis.spring.support.SqlSessionDaoSupport;
import org.springframework.util.ReflectionUtils;

import com.wwinsoft.modules.orm.Page;

/**
 * Mybatis pagination tool
 * startRow,endRow : start with 1 for oralce
 * offset,limit : startwith 0  for mysql
 *
 */
@SuppressWarnings("unchecked")
public class MyBatisDao extends SqlSessionDaoSupport {

	public <T> Page<T> selectPage(Page<T> page, String statementName, Object parameter) {
		String countStatementName = statementName + "_count";
		return selectPage(page, statementName, countStatementName, parameter);
	}

	public <T> Page<T> selectPage(Page<T> page, String statementName, String countStatementName, Object parameter) {

		Number totalItems = (Number) getSqlSession().selectOne(countStatementName, parameter);

		if (totalItems != null && totalItems.longValue() > 0) {
			List list = getSqlSession().selectList(statementName, toParameterMap(parameter,page), new RowBounds(page.getOffset(),page.getPageSize()));
			page.setResult(list);
			page.setTotalCount(totalItems.longValue());
		}
		return page;
	}
    
    protected List selectList(String statement, Object parameter){
        Map map = toParameterMap(parameter);
        return getSqlSession().selectList(statement, map);
    }

	protected static Map toParameterMap(Object parameter, Page p) {
		Map map = toParameterMap(parameter);
		map.put("startRow", p.getStartRow());
		map.put("endRow", p.getEndRow());
		map.put("offset", p.getOffset());
		map.put("limit", p.getPageSize());
        if(p.isOrderBySetted()){
            map.put("orderBy",p.getOrderBy());
            map.put("order",p.getOrder());
        }
		return map;
	}

	protected static Map toParameterMap(Object parameter) {
		if (parameter instanceof Map) {
			return (Map) parameter;
		} else {
			try {
				return PropertyUtils.describe(parameter);
			} catch (Exception e) {
				ReflectionUtils.handleReflectionException(e);
				return null;
			}
		}
	}
}
